#include "ConnectedComponents.h"
#include "../utils/Logger.h"

ConnectedComponents::ConnectedComponents(Effects *effects) :
        effects(effects)
{
}

ConnectedComponents::~ConnectedComponents() {
    if (effects)
        delete effects;
}

IplImage* ConnectedComponents::apply(const IplImage* in) {
    Log << "Applying connected components effect." << endl;

    IplImage *tmp = (IplImage*) in;
    if (NULL != effects && effects->any()) {
        tmp = effects->apply(in);
    }
    if (1 != tmp->nChannels) {
        IplImage *tmp2 = grayEffect.apply(tmp);
        if (in != tmp)
            cvReleaseImage(&tmp);
        tmp = tmp2;
    }

    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* contours = NULL;
    cvFindContours(tmp, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL);

    cvReleaseImage(&tmp);

    double biggestContourArea = -1;
    CvSeq *biggetContour = NULL;

    for (; contours != NULL; contours = contours->h_next) {
        double area = cvContourArea(contours);
        if (area > biggestContourArea) {
            biggetContour = contours;
            biggestContourArea = area;
        }
    }

    CvMemStorage* storage2 = cvCreateMemStorage();
    biggetContour = cvApproxPoly(biggetContour, sizeof(CvContour), storage2, CV_POLY_APPROX_DP, 50);
//    biggetContour = cvConvexHull2(biggetContour, storage2, CV_CLOCKWISE, 1);

    IplImage *mask = cvCreateImage(cvSize(in->width, in->height), in->depth, in->nChannels);
    cvZero(mask);
    cvDrawContours(mask, biggetContour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), -1, CV_FILLED);

    cvReleaseMemStorage(&storage);
    cvReleaseMemStorage(&storage2);

    IplImage *out = cvCreateImage(cvSize(in->width, in->height), in->depth, in->nChannels);
    cvAnd(in, mask, out);
//    cvCopy(mask, out);

    cvReleaseImage(&mask);

    return out;
}
